home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / dbmalloc / datamc.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  348 lines

  1.  
  2. /*
  3.  * (c) Copyright 1990, 1991, 1992 Conor P. Cahill (cpcahil@virtech.vti.com)
  4.  *
  5.  * This software may be distributed freely as long as the following conditions
  6.  * are met:
  7.  *         * the distribution, or any derivative thereof, may not be
  8.  *          included as part of a commercial product
  9.  *        * full source code is provided including this copyright
  10.  *        * there is no charge for the software itself (there may be
  11.  *          a minimal charge for the copying or distribution effort)
  12.  *        * this copyright notice is not modified or removed from any
  13.  *          source file
  14.  */
  15.  
  16. /*
  17.  * datamc.c - this module contains functions designed to efficiently 
  18.  *          copy memory areas in a portable fasion
  19.  *
  20.  * The configure script will usually override this module with a copy
  21.  * of the system suplied memcpy() utility if it can figure out how to
  22.  * convert the module name to DataMS.
  23.  */
  24. #ifndef lint
  25. static
  26. char rcs_hdr[] = "$Id: datamc.c,v 1.7 1992/08/22 16:27:13 cpcahil Exp $";
  27. #endif
  28.  
  29. #include <stdio.h>
  30. #include "mallocin.h"
  31.  
  32. typedef int word;
  33.  
  34. #define wordmask (sizeof(word)-1)
  35.  
  36. #ifndef DONT_USE_ASM
  37. #ifdef i386
  38. #define ASM_MEMCPY    1
  39.  
  40. /*
  41.  * DataMemcpy() - asm version of memcpy for use on 386 architecture systems.
  42.  *          This is much faster than performing the operation directly.
  43.  *          Note that the operation is performed by the use of word
  44.  *          moves followed by byte moves and it doesn't matter that
  45.  *          the word moves are not on a word aligned offset.
  46.  *
  47.  * This function differs from the system memcpy in that it correcly handles
  48.  * overlapping memory regions.  This is a requirement here because this is
  49.  * the same function that is called from memmove, memcpy, and bcopy.
  50.  */
  51. /*
  52.  * DataMemcpy(tgt,src,len)
  53.  */
  54.     asm("    .text");
  55.     asm("    .align 4");
  56. #ifdef USE_UNDERSCORE
  57.     asm("    .globl _DataMC");
  58.     asm("_DataMC:");
  59. #else
  60.     asm("    .globl DataMC");
  61.     asm("DataMC:");
  62. #endif
  63.     asm("    pushl  %edi");
  64.     asm("    pushl  %esi");
  65.     asm("    pushl  %ebx");
  66.  
  67.     /*
  68.      * get tgt -> edi
  69.      *     src -> esi
  70.      *     len -> ecx
  71.      */
  72.     asm("    movl   16(%esp),%edi");
  73.     asm("    movl   20(%esp),%esi");
  74.     asm("    movl   24(%esp),%ecx");
  75.  
  76.     /*
  77.      * compare target to src
  78.      */
  79.      asm("    cmpl   %edi,%esi");
  80.     /*
  81.      * if( tgt == src ) nothing to do, so return
  82.      */
  83.     asm("   je     .memdone"); 
  84.     /*
  85.      * if(    (tgt > src)
  86.      */
  87.     asm("    jg     .movenorm");
  88.     /*
  89.      *     &&  tgt < (src + len)
  90.      */
  91.     asm("    movl    %esi,%eax");
  92.     asm("    addl    %ecx,%eax");
  93.     asm("    cmpl    %edi,%eax");
  94.     asm("   jl    .movenorm");
  95.  
  96.     /*
  97.      * {
  98.      */
  99.         /*
  100.          * move the pointers to the end of the data area to be 
  101.          * moved and set the direction flag so that 
  102.          */
  103.  
  104.         /*
  105.          *     && ( len >= 4 ) )
  106.          */
  107.         asm("    cmpl    $4,%ecx");
  108.         asm("    jl    .moveshort");
  109.         /*
  110.          * {
  111.          */
  112.  
  113.             asm("    addl    %ecx,%edi");
  114.             asm("    subl    $4,%edi");
  115.             asm("    addl    %ecx,%esi");
  116.             asm("    subl    $4,%esi");
  117.             asm("    xor    %ebx,%ebx");
  118.             asm("    jmp    .moveback");
  119.         /* 
  120.           * }
  121.          * else
  122.          * {
  123.           */
  124.             asm("    addl    %ecx,%edi");
  125.             asm("    addl    %ecx,%esi");
  126.             asm(".moveshort:");
  127.             asm("    movl    $1,%ebx");
  128.         /* 
  129.          * }
  130.           */
  131.         asm(".moveback:");
  132.         asm("    std");
  133.         asm("    jmp    .movedata");
  134.     /*
  135.      * }
  136.      * else
  137.      * {
  138.       */
  139.         asm(".movenorm:");
  140.         asm("    mov    $1,%ebx");
  141.  
  142.     /*
  143.      * }
  144.      */
  145.  
  146.     /*
  147.      * now go move the data
  148.      */
  149.     asm(".movedata:");
  150.     asm("    movl   %edi,%eax");
  151.     asm("    movl   %ecx,%edx");
  152.     asm("    shrl   $02,%ecx");
  153. #ifdef USE_REPE
  154.     asm("    repe");
  155. #else
  156.     asm("    repz");
  157. #endif
  158.     asm("    movsl ");
  159.  
  160.     /*
  161.      * if we were performing a negative move, adjust the pointer
  162.      * so that it points to the previous byte (right now it points
  163.       * to the previous word
  164.      */
  165.     asm("    cmpl    $0,%ebx");
  166.     asm("   jnz    .movedata2");
  167.     /*
  168.      * {
  169.      */
  170.         asm("    addl    $3,%edi");
  171.         asm("    addl    $3,%esi");
  172.     /* 
  173.      * }
  174.      */
  175.  
  176.     asm(".movedata2:");    
  177.     asm("    movl   %edx,%ecx");
  178.     asm("    andl   $03,%ecx");
  179. #ifdef USE_REPE
  180.     asm("    repe");
  181. #else
  182.     asm("    repz");
  183. #endif
  184.     asm("    movsb ");
  185.  
  186.     asm("    cld");
  187.  
  188.     /*
  189.      * return
  190.      */
  191.     asm(".memdone:");
  192.     asm("    popl    %ebx");
  193.     asm("    popl    %esi");
  194.     asm("    popl    %edi");
  195.     asm("    ret");
  196.  
  197.  
  198. #endif /* i386 */
  199. #endif /* DONT_USE_ASM */
  200.  
  201. #ifndef ASM_MEMCPY
  202.  
  203. void
  204. DataMC(ptr1,ptr2,len)
  205.     MEMDATA            * ptr1;
  206.     CONST MEMDATA        * ptr2;
  207.     MEMSIZE              len;
  208. {
  209.     register MEMSIZE      i;
  210.     register char        * myptr1;
  211.     register CONST char    * myptr2;
  212.  
  213.     if( len <= 0 )
  214.     {
  215.         return;
  216.     }
  217.  
  218.     myptr1 = ptr1;
  219.     myptr2 = ptr2;
  220.  
  221.     /*
  222.      * while the normal memcpy does not guarrantee that it will 
  223.      * handle overlapping memory correctly, we will try...
  224.      */
  225.     if( (myptr1 > myptr2) && (myptr1 < (myptr2+len)) )
  226.     {
  227.         myptr1 += len;
  228.         myptr2 += len;
  229.  
  230.         if( (((long)myptr1)&wordmask) == (((long)myptr2)&wordmask))
  231.         {
  232.             /*
  233.              * if the pointer is not on an even word boundary
  234.              */
  235.             if( (i = (((long)myptr1) & wordmask)) != 0 )
  236.             {
  237.                 /*
  238.                  * process an extra byte at the word boundary
  239.                  * itself
  240.                  */
  241.                 while( (i-- > 0) && (len > 0) )
  242.                 {
  243.                     *(--myptr1) = *(--myptr2);
  244.                     len--;
  245.                 }
  246.             }
  247.  
  248.             /*
  249.              * convert remaining number of bytes to number of words
  250.              */
  251.             i = len >> (sizeof(word)/2);
  252.  
  253.             /*
  254.              * and copy them
  255.              */
  256.             while( i-- > 0 )
  257.             {
  258.                 myptr1 -= sizeof(word);
  259.                 myptr2 -= sizeof(word);
  260.                 *(word *)myptr1 = *(CONST word *)myptr2;
  261.             }
  262.  
  263.             /*
  264.              * and now handle any trailing bytes
  265.              */
  266.             if( (i = (len & wordmask)) != 0 )
  267.             {
  268.                 while( i-- > 0 )
  269.                 {
  270.                     *(--myptr1) = *(--myptr2);
  271.                 }
  272.             }
  273.         }
  274.         /*
  275.          * else we have to do it on a byte by byte basis
  276.          */
  277.         else
  278.         {
  279.             while( len-- > 0 )
  280.             {
  281.                 *(--myptr1) = *(--myptr2);
  282.             }
  283.         }
  284.     }
  285.     else
  286.     {
  287.         /*
  288.          * if we can make this move on even boundaries
  289.          */
  290.         if( (((long)myptr1)&wordmask) == (((long)myptr2)&wordmask) )
  291.         {
  292.             /*
  293.              * if the pointer is not on an even word boundary
  294.              */
  295.             if( (i = (((long)myptr1) & wordmask)) != 0 )
  296.             {
  297.                 while( (i++ < sizeof(word)) && (len > 0) )
  298.                 {
  299.                     *(myptr1++) = *(myptr2++);
  300.                     len--;
  301.                 }
  302.             }
  303.  
  304.             /*
  305.              * convert remaining number of bytes to number of words
  306.              */
  307.             i = len >> (sizeof(word)/2);
  308.  
  309.             /*
  310.              * and copy them
  311.              */
  312.             while( i-- > 0 )
  313.             {
  314.                 *(word *)myptr1 = *(CONST word *)myptr2;
  315.                 myptr1 += sizeof(word);
  316.                 myptr2 += sizeof(word);
  317.             }
  318.  
  319.             /*
  320.              * and now handle any trailing bytes
  321.              */
  322.             if( (i = (len & wordmask)) != 0 )
  323.             {
  324.                 while( i-- > 0 )
  325.                 {
  326.                     *(myptr1++) = *(myptr2++);
  327.                 }
  328.             }
  329.         }
  330.         /*
  331.          * else we have to handle it a byte at a time
  332.          */
  333.         else
  334.         {
  335.             while( len-- > 0 )
  336.             {
  337.                 *(myptr1++) = *(myptr2++);
  338.             }
  339.         }
  340.     }
  341.     
  342.     return;
  343.  
  344. } /* DataMC(... */
  345.  
  346. #endif /* ASM_MEMCPY */
  347.  
  348.